#pragma once
#include "../Common/Logger.hpp"
#include "../Common/Tool.hpp"
#include <fcntl.h>
#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

namespace OJ
{
  class Compiler
  {
  public:
    // 编译功能
    static bool compile(const std::string &file_name)
    {
      pid_t pid = fork();
      if (pid < 0)
      {
        // 说明子进程创建失败
        ELOG("创建子进程失败");
        return false;
      }
      else if (pid == 0)
      {
        umask(0);
        // 子进程
        // 打开错误文件,如果没有就创建
        int fd = open(Tool::PathBuilder::buildCompileErrorPath(file_name).c_str(), O_WRONLY | O_CREAT, 0644);
        if (fd < 0)
        {
          ELOG("打开错误文件失败");
          exit(1);
        }

        // 重定向错误输出
        dup2(fd, 2);
        // 由子进程来执行编译操作
        //g++ -std=c++11 source.cpp -o executable
        execlp("g++", "g++", "-std=c++11", Tool::PathBuilder::buildSourcePath(file_name).c_str(), "-o",
               Tool::PathBuilder::buildExecutablePath(file_name).c_str(), nullptr);
        // 关闭错误文件
        close(fd);
        // 子进程执行完毕,退出
        exit(2);
      }
      else
      {
        // 父进程
        // 查看TempFiles目录下是否有编译后的可执行文件
        waitpid(pid, nullptr, 0);
        if (Tool::FileHandler::isFileExist(Tool::PathBuilder::buildExecutablePath(file_name)))
        {
          DLOG("文件:%s编译成功", Tool::PathBuilder::buildSourcePath(file_name).c_str());
          return true;
        }
        else
        {
          ELOG("文件:%s编译失败", Tool::PathBuilder::buildSourcePath(file_name).c_str());
          return false;
        }
      }
    }

  public:
    // 构造函数和析构函数
    Compiler() {}
    ~Compiler() {}
  };
}